import os
import requests
import pandas as pd
import json
from datetime import datetime, timedelta
import time
import sys

# 添加项目根目录到系统路径
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../../')))

from config.config import DATA_CONFIG

class WeatherDataCollector:
    """
    天气数据采集类，负责从各种天气API获取数据
    """
    def __init__(self):
        self.raw_data_path = os.path.join(os.path.dirname(__file__), '../../', DATA_CONFIG['raw_data_path'])
        self.cities = DATA_CONFIG['default_cities']
        
        # 确保原始数据目录存在
        os.makedirs(self.raw_data_path, exist_ok=True)
        
        # 获取API密钥
        self.weatherapi_key = os.environ.get(DATA_CONFIG['api']['weatherapi']['key_env_var'])
        
        # 从配置文件获取心知天气API密钥
        # 心知天气API需要使用完整的API密钥
        # 根据心知天气API文档，需要使用正确格式的API密钥
        # 尝试从环境变量获取，如果没有则使用配置文件中的密钥
        self.seniverse_key = os.environ.get(DATA_CONFIG['api']['seniverse']['key_env_var']) or DATA_CONFIG['api']['seniverse']['public_key']
        
        # 检查心知天气API密钥是否存在
        if not self.seniverse_key:
            print(f"警告: 未找到心知天气API密钥，请设置环境变量 {DATA_CONFIG['api']['seniverse']['key_env_var']}")
        else:
            print(f"使用心知天气API密钥: {self.seniverse_key[:5]}...{self.seniverse_key[-5:] if len(self.seniverse_key) > 10 else ''}")
        
        # 检查API密钥是否存在
        if not self.weatherapi_key:
            print(f"警告: 未找到WeatherAPI密钥，请设置环境变量 {DATA_CONFIG['api']['weatherapi']['key_env_var']}")
    
    def get_current_weather(self, api_source='seniverse'):
        """
        获取当前天气数据
        api_source: 'openweathermap', 'weatherapi', 'seniverse' 或 'heweather'
        """
        if api_source == 'openweathermap':
            return self._get_current_weather_openweathermap()
        elif api_source == 'weatherapi':
            return self._get_current_weather_weatherapi()
        elif api_source == 'seniverse':
            return self._get_current_weather_seniverse()
        elif api_source == 'heweather':
            return self._get_current_weather_heweather()
        else:
            print(f"未知的API来源: {api_source}")
            return None
    


    def _get_current_weather_heweather(self):
        """
        从和风天气API获取当前天气数据
        """
        if not self.heweather_key:
            print("缺少和风天气API密钥")
            return None

        base_url = DATA_CONFIG['heweather']['base_url']
        locations = DATA_CONFIG['heweather']['locations']

        all_data = []
        for city in locations:
            try:
                url = f"{base_url}weather/now?location={city['id']}&key={self.heweather_key}"
                response = requests.get(url)
                
                if response.status_code == 200:
                    data = response.json()
                    weather_data = {
                        'city': city['name'],
                        'city_id': city['id'],
                        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                        'temp': data['now']['temp'],
                        'humidity': data['now']['humidity'],
                        'pressure': data['now']['pressure'],
                        'wind_speed': data['now']['windSpeed'],
                        'wind_direction': data['now']['wind360'],
                        'weather_condition': data['now']['text'],
                        'data_source': 'heweather'
                    }
                    all_data.append(weather_data)
                    print(f"成功获取 {city['name']} 的当前天气数据")
                else:
                    print(f"获取 {city['name']} 数据失败: {response.status_code}")
                time.sleep(1)
            except Exception as e:
                print(f"获取和风天气数据出错: {str(e)}")

        if all_data:
            df = pd.DataFrame(all_data)
            output_path = os.path.join(self.raw_data_path, 'current_weather_raw.csv')
            df.to_csv(output_path, mode='a', header=not os.path.exists(output_path), index=False)
            print(f"和风天气数据已保存至: {output_path}")
            return df
        return None
        
    def _get_current_weather_seniverse(self):
        """
        从心知天气API获取当前天气数据
        """
        if not self.seniverse_key:
            print("缺少心知天气API密钥")
            return None
        
        base_url = DATA_CONFIG['api']['seniverse']['base_url']
        language = DATA_CONFIG['api']['seniverse']['language']
        unit = DATA_CONFIG['api']['seniverse']['unit']
        
        # 尝试使用环境变量中的API密钥
        api_key = os.environ.get(DATA_CONFIG['api']['seniverse']['key_env_var'])
        if api_key:
            # 优先使用环境变量中的API密钥
            key_to_use = api_key
        else:
            # 否则使用配置文件中的密钥
            key_to_use = self.seniverse_key
        
        all_data = []
        
        for city in self.cities:
            try:
                # 心知天气API使用城市名称查询
                # 使用正确的API密钥格式
                url = f"{base_url}weather/now.json?key={key_to_use}&location={city['name']}&language={language}&unit={unit}"
                print(f"请求URL: {url}")
                response = requests.get(url)
                
                if response.status_code == 200:
                    data = response.json()
                    
                    # 提取需要的数据
                    weather_data = {
                        'city': city['name'],
                        'city_id': city['id'],
                        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                        'temp': data['results'][0]['now']['temperature'],
                        'humidity': data['results'][0]['now']['humidity'],
                        'wind_speed': data['results'][0]['now']['wind_speed'],
                        'wind_direction': data['results'][0]['now']['wind_direction'],
                        'weather_condition': data['results'][0]['now']['text'],
                        'data_source': 'seniverse'
                    }
                    
                    all_data.append(weather_data)
                    print(f"成功获取 {city['name']} 的当前天气数据")
                else:
                    print(f"获取 {city['name']} 的天气数据失败: {response.status_code} - {response.text}")
            
            except Exception as e:
                print(f"获取 {city['name']} 的天气数据时出错: {e}")
            
            # 添加延迟，避免API请求过于频繁
            time.sleep(1)
        
        if all_data:
            # 转换为DataFrame
            df = pd.DataFrame(all_data)
            
            # 保存为CSV
            output_path = os.path.join(self.raw_data_path, 'current_weather_raw.csv')
            df.to_csv(output_path, index=False)
            print(f"当前天气数据已保存至: {output_path}")
            
            return df
        else:
            print("未获取到任何天气数据")
            return None
    
    def _get_current_weather_weatherapi(self):
        """
        从WeatherAPI获取当前天气数据
        """
        if not self.weatherapi_key:
            print("缺少WeatherAPI密钥")
            return None
        
        base_url = DATA_CONFIG['api']['weatherapi']['base_url']
        
        all_data = []
        
        for city in self.cities:
            try:
                url = f"{base_url}current.json?key={self.weatherapi_key}&q={city['name']}&lang=zh"
                response = requests.get(url)
                
                if response.status_code == 200:
                    data = response.json()
                    
                    # 提取需要的数据
                    weather_data = {
                        'city': city['name'],
                        'city_id': city['id'],
                        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                        'temp': data['current']['temp_c'],
                        'humidity': data['current']['humidity'],
                        'pressure': data['current']['pressure_mb'],
                        'wind_speed': data['current']['wind_kph'] / 3.6,  # 转换为m/s
                        'wind_direction': data['current']['wind_degree'],
                        'weather_condition': data['current']['condition']['text'],
                        'clouds': data['current']['cloud'],
                        'data_source': 'weatherapi'
                    }
                    
                    all_data.append(weather_data)
                    print(f"成功获取 {city['name']} 的当前天气数据")
                else:
                    print(f"获取 {city['name']} 的天气数据失败: {response.status_code} - {response.text}")
            
            except Exception as e:
                print(f"获取 {city['name']} 的天气数据时出错: {e}")
            
            # 添加延迟，避免API请求过于频繁
            time.sleep(1)
        
        if all_data:
            # 转换为DataFrame
            df = pd.DataFrame(all_data)
            
            # 保存为CSV
            output_path = os.path.join(self.raw_data_path, 'current_weather_raw.csv')
            df.to_csv(output_path, index=False)
            print(f"当前天气数据已保存至: {output_path}")
            
            return df
        else:
            print("未获取到任何天气数据")
            return None

    def _get_current_weather(self):
        """
        从和风天气API获取当前天气数据
        """
        if not self.heweather_key:
            print("缺少和风天气API密钥")
            return None

        base_url = DATA_CONFIG['heweather']['base_url']
        locations = DATA_CONFIG['heweather']['locations']

        all_data = []
        for city in locations:
            try:
                url = f"{base_url}weather/now?location={city['id']}&key={self.heweather_key}"
                response = requests.get(url)
                
                if response.status_code == 200:
                    data = response.json()
                    weather_data = {
                        'city': city['name'],
                        'city_id': city['id'],
                        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                        'temp': data['now']['temp'],
                        'humidity': data['now']['humidity'],
                        'pressure': data['now']['pressure'],
                        'wind_speed': data['now']['windSpeed'],
                        'wind_direction': data['now']['wind360'],
                        'weather_condition': data['now']['text'],
                        'data_source': 'heweather'
                    }
                    all_data.append(weather_data)
                    print(f"成功获取 {city['name']} 的当前天气数据")
                else:
                    print(f"获取 {city['name']} 数据失败: {response.status_code}")
                time.sleep(1)
            except Exception as e:
                print(f"获取和风天气数据出错: {str(e)}")

        if all_data:
            df = pd.DataFrame(all_data)
            output_path = os.path.join(self.raw_data_path, 'current_weather_raw.csv')
            df.to_csv(output_path, mode='a', header=not os.path.exists(output_path), index=False)
            print(f"和风天气数据已保存至: {output_path}")
            return df
        return None
        
    def _get_current_weather_seniverse(self):
        """
        从心知天气API获取当前天气数据
        """
        if not self.seniverse_key:
            print("缺少心知天气API密钥")
            return None
        
        base_url = DATA_CONFIG['api']['seniverse']['base_url']
        language = DATA_CONFIG['api']['seniverse']['language']
        unit = DATA_CONFIG['api']['seniverse']['unit']
        
        # 尝试使用环境变量中的API密钥
        api_key = os.environ.get(DATA_CONFIG['api']['seniverse']['key_env_var'])
        if api_key:
            # 优先使用环境变量中的API密钥
            key_to_use = api_key
        else:
            # 否则使用配置文件中的密钥
            key_to_use = self.seniverse_key
        
        all_data = []
        
        for city in self.cities:
            try:
                # 心知天气API使用城市名称查询
                # 使用正确的API密钥格式
                url = f"{base_url}weather/now.json?key={key_to_use}&location={city['name']}&language={language}&unit={unit}"
                print(f"请求URL: {url}")
                response = requests.get(url)
                
                if response.status_code == 200:
                    data = response.json()
                    
                    # 提取需要的数据
                    weather_data = {
                        'city': city['name'],
                        'city_id': city['id'],
                        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                        'temp': data['results'][0]['now']['temperature'],
                        'humidity': data['results'][0]['now']['humidity'],
                        'wind_speed': data['results'][0]['now']['wind_speed'],
                        'wind_direction': data['results'][0]['now']['wind_direction'],
                        'weather_condition': data['results'][0]['now']['text'],
                        'data_source': 'seniverse'
                    }
                    
                    all_data.append(weather_data)
                    print(f"成功获取 {city['name']} 的当前天气数据")
                else:
                    print(f"获取 {city['name']} 的天气数据失败: {response.status_code} - {response.text}")
            
            except Exception as e:
                print(f"获取 {city['name']} 的天气数据时出错: {e}")
            
            # 添加延迟，避免API请求过于频繁
            time.sleep(1)
        
        if all_data:
            # 转换为DataFrame
            df = pd.DataFrame(all_data)
            
            # 保存为CSV
            output_path = os.path.join(self.raw_data_path, 'current_weather_raw.csv')
            df.to_csv(output_path, index=False)
            print(f"当前天气数据已保存至: {output_path}")
            
            return df
        else:
            print("未获取到任何天气数据")
            return None
    
    def get_weather_forecast(self, days=5, api_source='seniverse'):
        """
        获取天气预报数据
        days: 预报天数
        api_source: 'openweathermap', 'weatherapi', 'seniverse' 或 'heweather'
        """
        if api_source == 'openweathermap':
            return self._get_forecast_openweathermap(days)
        elif api_source == 'weatherapi':
            return self._get_forecast_weatherapi(days)
        elif api_source == 'seniverse':
            return self._get_forecast_seniverse(days)
        else:
            print(f"未知的API来源: {api_source}")
            return None
    
    def _get_forecast_openweathermap(self, days=5):
        """
        从OpenWeatherMap API获取天气预报数据
        """
        if not self.openweathermap_api_key:
            print("缺少OpenWeatherMap API密钥")
            return None
        
        base_url = DATA_CONFIG['api']['openweathermap']['base_url']
        units = DATA_CONFIG['api']['openweathermap']['units']
        
        all_data = []
        
        for city in self.cities:
            try:
                # OpenWeatherMap的免费API只提供5天/3小时的预报
                url = f"{base_url}forecast?id={city['id']}&appid={self.openweathermap_api_key}&units={units}&lang=zh_cn"
                response = requests.get(url)
                
                if response.status_code == 200:
                    data = response.json()
                    
                    # 提取预报数据
                    for forecast in data['list']:
                        forecast_time = datetime.fromtimestamp(forecast['dt'])
                        
                        # 只保留指定天数内的预报
                        if forecast_time <= datetime.now() + timedelta(days=days):
                            forecast_data = {
                                'city': city['name'],
                                'city_id': city['id'],
                                'forecast_time': forecast_time.strftime('%Y-%m-%d %H:%M:%S'),
                                'temp': forecast['main']['temp'],
                                'temp_min': forecast['main']['temp_min'],
                                'temp_max': forecast['main']['temp_max'],
                                'humidity': forecast['main']['humidity'],
                                'pressure': forecast['main']['pressure'],
                                'wind_speed': forecast['wind']['speed'],
                                'wind_direction': forecast['wind']['deg'],
                                'weather_condition': forecast['weather'][0]['main'],
                                'weather_description': forecast['weather'][0]['description'],
                                'clouds': forecast['clouds']['all'],
                                'data_source': 'openweathermap'
                            }
                            
                            all_data.append(forecast_data)
                    
                    print(f"成功获取 {city['name']} 的天气预报数据")
                else:
                    print(f"获取 {city['name']} 的天气预报失败: {response.status_code} - {response.text}")
            
            except Exception as e:
                print(f"获取 {city['name']} 的天气预报时出错: {e}")
            
            # 添加延迟，避免API请求过于频繁
            time.sleep(1)
        
        if all_data:
            # 转换为DataFrame
            df = pd.DataFrame(all_data)
            
            # 保存为CSV
            output_path = os.path.join(self.raw_data_path, 'weather_forecast_raw.csv')
            df.to_csv(output_path, index=False)
            print(f"天气预报数据已保存至: {output_path}")
            
            return df
        else:
            print("未获取到任何天气预报数据")
            return None
    
    def _get_forecast_weatherapi(self, days=5):
        """
        从WeatherAPI获取天气预报数据
        """
        if not self.weatherapi_key:
            print("缺少WeatherAPI密钥")
            return None
        
        base_url = DATA_CONFIG['api']['weatherapi']['base_url']
        
        # 确保天数在API限制范围内
        days = min(days, 10)  # WeatherAPI免费版最多10天
        
        all_data = []
        
    def _get_forecast_seniverse(self, days=3):
        """
        从心知天气API获取天气预报数据
        """
        if not self.seniverse_key:
            print("缺少心知天气API密钥")
            return None
        
        base_url = DATA_CONFIG['api']['seniverse']['base_url']
        language = DATA_CONFIG['api']['seniverse']['language']
        unit = DATA_CONFIG['api']['seniverse']['unit']
        
        # 确保天数在API限制范围内
        days = min(days, 3)  # 心知天气免费版最多3天
        
        # 尝试使用环境变量中的API密钥
        api_key = os.environ.get(DATA_CONFIG['api']['seniverse']['key_env_var'])
        if api_key:
            # 优先使用环境变量中的API密钥
            key_to_use = api_key
        else:
            # 否则使用配置文件中的密钥
            key_to_use = self.seniverse_key
            
        all_data = []
        
        for city in self.cities:
            try:
                # 使用正确的API请求格式
                url = f"{base_url}weather/daily.json?key={key_to_use}&location={city['name']}&language={language}&unit={unit}&days={days}"
                print(f"请求URL: {url}")
                response = requests.get(url)
                
                if response.status_code == 200:
                    data = response.json()
                    
                    # 提取预报数据 - 修正数据结构以匹配心知天气API的返回格式
                    for day in data['results'][0]['daily']:
                        forecast_date = day['date']
                        
                        # 每日预报
                        day_forecast = {
                            'city': city['name'],
                            'city_id': city['id'],
                            'forecast_time': f"{forecast_date} 00:00:00",
                            'temp': (float(day['high']) + float(day['low'])) / 2,  # 平均温度
                            'temp_min': day['low'],
                            'temp_max': day['high'],
                            'humidity': day.get('humidity', ''),  # 心知天气可能不提供湿度
                            'wind_speed': day['wind_speed'],
                            'wind_direction': day['wind_direction'],
                            'weather_condition': day['text_day'],
                            'data_source': 'seniverse',
                            'forecast_type': 'daily'
                        }
                        
                        all_data.append(day_forecast)
                    
                    print(f"成功获取 {city['name']} 的天气预报数据")
                else:
                    print(f"获取 {city['name']} 的天气预报失败: {response.status_code} - {response.text}")
            
            except Exception as e:
                print(f"获取 {city['name']} 的天气预报时出错: {e}")
            
            # 添加延迟，避免API请求过于频繁
            time.sleep(1)
        
        if all_data:
            # 转换为DataFrame
            df = pd.DataFrame(all_data)
            
            # 保存为CSV
            output_path = os.path.join(self.raw_data_path, 'weather_forecast_raw.csv')
            df.to_csv(output_path, index=False)
            print(f"天气预报数据已保存至: {output_path}")
            
            return df
        else:
            print("未获取到任何天气预报数据")
            return None
    
    def get_historical_weather(self, days_back=30, api_source='weatherapi'):
        """
        获取历史天气数据
        days_back: 回溯的天数
        api_source: 目前只支持 'weatherapi'，因为OpenWeatherMap的历史数据需要付费订阅
        """
        if api_source != 'weatherapi':
            print(f"历史天气数据目前只支持WeatherAPI")
            return None
        
        return self._get_historical_weatherapi(days_back)
    
    def _get_historical_weatherapi(self, days_back=30):
        """
        从WeatherAPI获取历史天气数据
        """
        if not self.weatherapi_key:
            print("缺少WeatherAPI密钥")
            return None
        
        base_url = DATA_CONFIG['api']['weatherapi']['base_url']
        
        # WeatherAPI免费版只能获取过去7天的数据
        days_back = min(days_back, 7)
        
        all_data = []
        
        # 计算日期范围
        end_date = datetime.now().date()
        start_date = end_date - timedelta(days=days_back)
        
        for city in self.cities:
            current_date = start_date
            
            while current_date <= end_date:
                try:
                    date_str = current_date.strftime('%Y-%m-%d')
                    url = f"{base_url}history.json?key={self.weatherapi_key}&q={city['name']}&dt={date_str}&lang=zh"
                    response = requests.get(url)
                    
                    if response.status_code == 200:
                        data = response.json()
                        
                        # 提取历史数据
                        day = data['forecast']['forecastday'][0]
                        
                        # 每日数据
                        day_data = {
                            'city': city['name'],
                            'city_id': city['id'],
                            'timestamp': f"{date_str} 00:00:00",
                            'temp': day['day']['avgtemp_c'],
                            'temp_min': day['day']['mintemp_c'],
                            'temp_max': day['day']['maxtemp_c'],
                            'humidity': day['day']['avghumidity'],
                            'wind_speed': day['day']['maxwind_kph'] / 3.6,  # 转换为m/s
                            'weather_condition': day['day']['condition']['text'],
                            'data_source': 'weatherapi',
                            'data_type': 'daily'
                        }
                        
                        all_data.append(day_data)
                        
                        # 每小时数据
                        for hour in day['hour']:
                            hour_time = hour['time']
                            
                            hour_data = {
                                'city': city['name'],
                                'city_id': city['id'],
                                'timestamp': hour_time,
                                'temp': hour['temp_c'],
                                'humidity': hour['humidity'],
                                'pressure': hour['pressure_mb'],
                                'wind_speed': hour['wind_kph'] / 3.6,  # 转换为m/s
                                'wind_direction': hour['wind_degree'],
                                'weather_condition': hour['condition']['text'],
                                'clouds': hour['cloud'],
                                'data_source': 'weatherapi',
                                'data_type': 'hourly'
                            }
                            
                            all_data.append(hour_data)
                        
                        print(f"成功获取 {city['name']} 在 {date_str} 的历史天气数据")
                    else:
                        print(f"获取 {city['name']} 在 {date_str} 的历史天气数据失败: {response.status_code} - {response.text}")
                
                except Exception as e:
                    print(f"获取 {city['name']} 在 {current_date} 的历史天气数据时出错: {e}")
                
                # 更新日期
                current_date += timedelta(days=1)
                
                # 添加延迟，避免API请求过于频繁
                time.sleep(1)
        
        if all_data:
            # 转换为DataFrame
            df = pd.DataFrame(all_data)
            
            # 保存为CSV
            output_path = os.path.join(self.raw_data_path, 'historical_weather_raw.csv')
            df.to_csv(output_path, index=False)
            print(f"历史天气数据已保存至: {output_path}")
            
            return df
        else:
            print("未获取到任何历史天气数据")
            return None